package com.lsh.util;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;

import java.io.*;
import java.net.SocketException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;

/**
 * FTP 上传下载工具类
 * @author wade
 * @date 2017年12月6日
 */
@Slf4j
public class FtpFileUtils {
    public static FTPClient ftp;
	public static ArrayList<String> arFiles;
	/**
	 * 
	 * @param path
	 *            上传到ftp服务器哪个路径下
	 * @param addr
	 *            地址
	 * @param port
	 *            端口号
	 * @param username
	 *            用户名
	 * @param password
	 *            密码
	 * @return
	 * @throws Exception
	 */
	public static boolean connect(String path, String addr, int port,
			String username, String password) {
		boolean result = false;
		ftp = new FTPClient();
		int reply;
		try {
			ftp.connect(addr, port);
			ftp.login(username, password);
			ftp.setRemoteVerificationEnabled(false);
			ftp.setFileType(FTPClient.BINARY_FILE_TYPE);
			reply = ftp.getReplyCode();
			if (!FTPReply.isPositiveCompletion(reply)) {
				ftp.disconnect();
				return result;
			}
			ftp.changeWorkingDirectory(path);
		} catch (Exception e) {
            throw new  RuntimeException("FtpFileUtils upload(2) :" + e.getMessage() + "\"");
        }
		result = true;
		return result;
	}

	/**
	 * @title upload
	 * @return void
	 * @exception :(Error note)
	 * @param file
	 *            上传的文件或文件夹
	 * @param path
	 *            上传的文件的路径
	 * @throws Exception
	 */
	public static void upload(File file, String path) {

		System.out.println(" file.isDirectory() : " + file.isDirectory());

		if (file.isDirectory()) {
			try {
				ftp.makeDirectory(file.getName());
				ftp.changeWorkingDirectory(file.getName());
				String[] files = file.list();
				for (int i = 0; i < files.length; i++) {
					File file1 = new File(file.getPath() + "\\" + files[i]);
					if (file1.isDirectory()) {
						upload(file1, path);
						ftp.changeToParentDirectory();
					} else {
						File file2 = new File(file.getPath() + "\\" + files[i]);
						FileInputStream input = new FileInputStream(file2);
						ftp.storeFile(file2.getName(), input);
						input.close();
					}
				}
			} catch (Exception e) {
				throw new  RuntimeException("FtpFileUtils upload(2) :" + e.getMessage() + "\"");
			}
		} else {
			File file2 = new File(file.getPath());

			System.out.println(" file.getPath() : " + file.getPath()
					+ " | file2.getName() : " + file2.getName());

			try {
				InputStream input = new FileInputStream(file2);
				if (!ftp.changeWorkingDirectory(path)) {
					 if (!makeDirectory(path)) {
						 log.info("创建目录【"+path+"】失败");
				     }
				}
				ftp.storeFile(file2.getName(), input);

				input.close(); // 关闭输入流
			} catch (Exception e) {
                throw new  RuntimeException("FtpFileUtils upload(2) :" + e.getMessage() + "\"");
			} 
		}
	}

	/**
	 * @title download
	 * @Description : FPT 下载文件方法
	 * @return void
	 * @exception :(Error note)
	 * @param reomvepath
	 *            下载的文件的路径
	 * @param fileName
	 *            下载的文件名
	 * @param localPath
	 *            下载的文件本地路径
	 * @throws Exception
	 */
	public static void download(String reomvepath, String fileName, String localPath)
			throws Exception {

		ftp.changeWorkingDirectory(reomvepath);

		// 列出该目录下所有文件
		FTPFile[] fs = ftp.listFiles();
		// 遍历所有文件，找到指定的文件
		for (FTPFile ff : fs) {
			if (ff.getName().equals(fileName)) {
				// 根据绝对路径初始化文件
				File localFile = new File(localPath + "/" + ff.getName());
				// 输出流
				OutputStream is = new FileOutputStream(localFile);
				// 下载文件
				ftp.retrieveFile(ff.getName(), is);
				System.out.println("下载成功!");
				is.close();
			}
		}

		ftp.logout(); // 退出连接

	}

    /**
     * 递归遍历出目录下面所有文件
     *
     * @param pathName 需要遍历的目录，必须以"/"开始和结束
     * @throws IOException
     */
    public static ArrayList<String> List(String pathName) throws IOException {
        if (pathName.startsWith("/") && pathName.endsWith("/")) {
            //更换目录到当前目录
            ftp.changeWorkingDirectory(pathName);
            FTPFile[] files = ftp.listFiles();
            for (FTPFile file : files) {
                if (file.isFile()) {
                    arFiles.add(file.getName());
                } else if (file.isDirectory()) {
                    // 需要加此判断。否则，ftp默认将‘项目文件所在目录之下的目录（./）’与‘项目文件所在目录向上一级目录下的目录（../）’都纳入递归，这样下去就陷入一个死循环了。需将其过滤掉。
                    if (!".".equals(file.getName()) && !"..".equals(file.getName())) {
                        List(pathName + file.getName() + "/");
                    }
                }
            }
        }
		return arFiles;
    }
	
	 /**
      * 关闭ftp连接
      */
     public static void closeFtp(){
         if (ftp!=null && ftp.isConnected()) {
             try {
                 ftp.disconnect();
             } catch (IOException e) {
                 e.printStackTrace();
             }
         }
     }
     
     /** 
      * 递归创建远程目录
      * 
      * @param dir 远程服务器绝对路径
      *            文件夹名称，不能含有特殊字符，如 \ 、/ 、: 、* 、?、 "、 <、>... 
     * @throws IOException 
      */  
     public static boolean makeDirectory(String dir) throws IOException {  
    	 boolean success = true;
         String directory = dir.substring(0, dir.lastIndexOf("/") + 1);
         // 如果远程目录不存在，则递归创建远程服务器目录
         if (!directory.equalsIgnoreCase("/")
                 && !ftp.changeWorkingDirectory(new String(directory))) {
        	 int start = 0;
             int end = 0;
             if (directory.startsWith("/")) {
                 start = 1;
             } else {
                 start = 0;
             }
             end = directory.indexOf("/", start);
             while (true) {
                 String subDirectory = new String(dir.substring(start, end));
                 if (!ftp.changeWorkingDirectory(subDirectory)) {
                     if (ftp.makeDirectory(subDirectory)) {
                         ftp.changeWorkingDirectory(subDirectory);
                     } else {
                         log.info("创建目录失败"+subDirectory);
                         success = false;
                         return success;
                     }
                 }
                 start = end + 1;
                 end = directory.indexOf("/", start);
                 // 检查所有目录是否创建完毕
                 if (end <= start) {
                     break;
                 }
             }
         }
         return success;
     }

     
	public static void main(String[] args) throws Exception {

		boolean lianjie = FtpFileUtils.connect("/", "180.153.41.111", 21,
				"lichunyu", "lichunyu");
		System.out.println("连接 是否成功：" + lianjie);

		// 上传
//		File file = new File("D:\\360Downloads\\1460094037.png");
		String path = "/credupload/"+new SimpleDateFormat("yyyy/MM/dd").format(new Date());
		boolean b = makeDirectory(path);
		System.out.println(b);
//		FtpFileUtils.upload(file, path);

		// 下载
		// t.download("/zhengzhenzhen", "11.png", "D:\\test");
		System.out.println("test");
	}
    /**
     * 获取FTPClient对象
     *
     * @param ftpHost     FTP主机服务器
     * @param ftpPassword FTP 登录密码
     * @param ftpUserName FTP登录用户名
     * @param ftpPort     FTP端口 默认为21
     * @return
     */
    public static FTPClient getFTPClient(String ftpHost, String ftpUserName,
                                         String ftpPassword, int ftpPort) {
        FTPClient ftpClient = new FTPClient();
        try {
            ftpClient = new FTPClient();
            ftpClient.connect(ftpHost, ftpPort);// 连接FTP服务器
            ftpClient.login(ftpUserName, ftpPassword);// 登陆FTP服务器
            if (!FTPReply.isPositiveCompletion(ftpClient.getReplyCode())) {
                System.out.println("未连接到FTP，用户名或密码错误。");
                log.info("未连接到FTP，用户名或密码错误。");
                ftpClient.disconnect();
            } else {
                System.out.println("FTP连接成功。");
                log.info("FTP连接成功。");
            }
        } catch (SocketException e) {
            e.printStackTrace();
            log.info("FTP的IP地址可能错误，请正确配置。");
            System.out.println("FTP的IP地址可能错误，请正确配置。");
        } catch (IOException e) {
            e.printStackTrace();
            log.info("FTP的端口错误,请正确配置。");
            System.out.println("FTP的端口错误,请正确配置。");
        }
        return ftpClient;
    }
	 /*
     * 从FTP服务器下载文件
     *
     * @param ftpHost FTP IP地址
     * @param ftpUserName FTP 用户名
     * @param ftpPassword FTP用户名密码
     * @param ftpPort FTP端口
     * @param ftpPath FTP服务器中文件所在路径 格式： ftptest/aa
     * @param localPath 下载到本地的位置 格式：H:/download
     * @param fileName 文件名称
     */
    public static void downloadFtpFile(String ftpHost, String ftpUserName,
                                       String ftpPassword, int ftpPort, String ftpPath, String localPath,
                                       String fileName) {

        FTPClient ftpClient = null;

        try {
            ftpClient = getFTPClient(ftpHost, ftpUserName, ftpPassword, ftpPort);
            ftpClient.setControlEncoding("UTF-8"); // 中文支持
            ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
            ftpClient.enterLocalPassiveMode();
            ftpClient.changeWorkingDirectory(ftpPath);

            File localFile = new File(localPath + File.separatorChar + fileName);
            OutputStream os = new FileOutputStream(localFile);
            ftpClient.retrieveFile(fileName, os);
            os.close();
            ftpClient.logout();

        } catch (FileNotFoundException e) {
        	log.info("没有找到" + ftpPath + "文件");
            System.out.println("没有找到" + ftpPath + "文件");
            e.printStackTrace();
        } catch (SocketException e) {
        	log.info("连接FTP失败.");
            System.out.println("连接FTP失败.");
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
            log.info("文件读取错误。");
            System.out.println("文件读取错误。");
            e.printStackTrace();
        }

    }

    /**
     * Description: 向FTP服务器上传文件
     * @param ftpHost FTP服务器hostname
     * @param ftpUserName 账号
     * @param ftpPassword 密码
     * @param ftpPort 端口
     * @param ftpPath  FTP服务器中文件所在路径 格式： ftptest/aa
     * @param fileName ftp文件名称
     * @param input 文件流
     * @return 成功返回true，否则返回false
     */
    public static boolean uploadFile(String ftpHost, String ftpUserName,
                                     String ftpPassword, int ftpPort, String ftpPath,
                                     String fileName,InputStream input) {
        boolean success = false;
        FTPClient ftpClient = null;
        try {
            int reply;
            ftpClient = getFTPClient(ftpHost, ftpUserName, ftpPassword, ftpPort);
            reply = ftpClient.getReplyCode();
            if (!FTPReply.isPositiveCompletion(reply)) {
                ftpClient.disconnect();
                return success;
            }
            ftpClient.setControlEncoding("UTF-8"); // 中文支持
            ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
            ftpClient.enterLocalPassiveMode();
            ftpClient.changeWorkingDirectory(ftpPath);

            ftpClient.storeFile(fileName, input);

            input.close();
            ftpClient.logout();
            success = true;
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (ftpClient.isConnected()) {
                try {
                    ftpClient.disconnect();
                } catch (IOException ioe) {
                }
            }
        }
        return success;
    }

}